'''
@author: oabalbin
Created on Nov 21, 2011

Creates a network based on a list of interaction objects (see class interaction)
'''
import sys
import logging
import numpy as np
import networkx as nx

class netBuilder():
    def __init__(self,dictOfInter):
        self.net = self.build(dictOfInter)
        
    def build(self,dictOfInter):
        '''
        Build Network
        '''
        
        return nx.from_dict_of_dicts(dictOfInter)

class netDiBuilder():
    def __init__(self,net=None,dictOfInter=None):
        '''
        From either a previous undericted networ or a dictionary of interactions
        '''
        if net is not None:
            self.net = self.diNet_build(net)
        elif dictOfInter is not None:
            self.net = nx.DiGraph()
            self.net = self.diNet_build_from_dict(dictOfInter) #nx.from_dict_of_dicts(dictOfInter)
    def diNet_build_from_dict(self,dictOfInter):
        '''
        It creates the network from a dictionary structure
        '''
        diNet = nx.DiGraph()
        for nodeA, edges in dictOfInter.iteritems():
            for nodeB, edge_att in edges.iteritems():
                #print nodeA,nodeB, edge_att                
                if edge_att['mode']=='expression':
                    print nodeA, nodeB, edge_att
                diNet.add_edge(nodeA,nodeB,edge_att)
        return diNet 
        
    def diNet_build(self,net):
        '''
        Net is graph in which edges have all the atributes of the interaction class
        score_ist = neighborhood, fusion, cooccurence, coexpression, 
                 experimental, indatabase, textmining, combined_score
        '''
        attlist=['experimental', 'indatabase'] # combined_score
        diNet = nx.DiGraph()
        
        for edge in net.edges_iter(data=True):
            #print edge
            interaction_type = edge[2]['mode']
            scores=self.get_string_weights(edge[2],attlist)
            weight=self.calc_STRING_combined_score(scores)
            edge_dict={'mode':interaction_type,'weight':weight}
            # Create the Network
            if interaction_type=='binding':
                # When mode=binding the interactions has not direction so we replace it for two edges
                diNet.add_edge(edge[0],edge[1],edge_dict)
                diNet.add_edge(edge[1],edge[0],edge_dict)
            if interaction_type=='expression':
                print "LAST NETWORK ", edge[0],edge[1]
                diNet.add_edge(edge[0],edge[1],edge_dict)
            else:
                diNet.add_edge(edge[0],edge[1],edge_dict)
        
        return diNet
            
    def get_string_weights(self,edgedict, attlist):
        '''
        '''
        scores=[]
        for at in attlist:
            scores.append(edgedict[at])
        
        return scores
    
    def calc_STRING_combined_score(self,scores_list):
        '''
        It calculatares the combine scores assuming a naive bayes approach in which source of information are independent
        The actual probability should be S =  1 - multplication (1-Si)
        Here we calculate rhe secon term because we want to lowest cost to the high confident interactions.
        '''
        edge_weight=1
        STRING_max_score = 1000.0
        for score in scores_list:
            score_i = 1.0 - float(score)/STRING_max_score
            edge_weight=edge_weight*score_i
        
        return edge_weight

